package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.UserThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsService wmNewsService;

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Override
    public PageResponseResult newsList(WmNewsPageReqDto dto) {

        //1.构建查询条件
        Short status = dto.getStatus();
        String keyword = dto.getKeyword();
        Integer channelId = dto.getChannelId();
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        Integer currentPage = dto.getPage();
        Integer pageSize = dto.getSize();


        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();

        //状态条件
        wrapper.eq(status != null,WmNews::getStatus,status);

        //关键字条件
        wrapper.like(StringUtils.isNotEmpty(keyword),WmNews::getTitle,keyword);

        //频道条件
        wrapper.eq(channelId != null,WmNews::getChannelId,channelId);

        //日期条件
        wrapper.between(beginPubDate != null && endPubDate != null,WmNews::getPublishTime,beginPubDate,endPubDate);

        //2.添加排序条件
        wrapper.orderByDesc(WmNews::getPublishTime);

        //3.构建分页条件
        Page<WmNews> page = new Page<>(currentPage,pageSize);

        //4.执行分页查询
        Page<WmNews> wmNewsPage = wmNewsMapper.selectPage(page, wrapper);
        Long total = wmNewsPage.getTotal();

        //构建结果并返回
        PageResponseResult pageResponseResult = new PageResponseResult(currentPage,pageSize,total.intValue());
        //写入数据
        pageResponseResult.setData(wmNewsPage.getRecords());
        return pageResponseResult;
    }

    @Override
    public ResponseResult submit(WmNewsDto dto) {

        //得到且补充参数
        WmNews wmNews = newsDto2News(dto);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.判断是否是草稿,草稿则返回
        Short status = dto.getStatus();
        if (status == 0) {

        }

        //得到文章内容图片
        String content = dto.getContent();
        List<String> contentImage = getContentImage(content);

        //如果是文章封面类型为自动(type=-1)要到内容中提取图片
        Short type = dto.getType();
        List<String> images = dto.getImages();
        List<String> coverImage = getCoverImage(type, images, contentImage);

        //内容图添加到wm_material表
        Boolean contentImageResult = addMaterial(wmNews.getId(), contentImage, 0);
        if (!contentImageResult) {
            throw new RuntimeException("wm_material表更新失败");
        }

        //封面图添加到wm_news_material表
        Boolean coverImageResult = addMaterial(wmNews.getId(), coverImage, 1);
        if (!coverImageResult) {
            throw new RuntimeException("wm_news_material表更新失败");
        }


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    //将数据插入数据表
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean addMaterial(Integer newsId, List<String> imagesList, Integer type){
        //判空
        if (CollectionUtils.isEmpty(imagesList)) {
            return true;
        }

        for (String url : imagesList) {
            //1.将内容图数据插入到wm_material表
            WmMaterial wmMaterial = new WmMaterial();
            wmMaterial.setUserId(UserThreadLocal.get().getId());
            wmMaterial.setUrl(url);
            wmMaterial.setIsCollection((short) 0);
            wmMaterial.setCreatedTime(new Date());
            wmMaterial.setType((short) 0);

            int insertResult = wmMaterialMapper.insert(wmMaterial);
            if (insertResult < 1) {
                throw new RuntimeException("wm_material表更新失败");
            }

            //2.将封面图数据插入到wm_news_material表
            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setMaterialId(wmMaterial.getId());
            newsMaterial.setNewsId(newsId);
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 1);
            int newsMaterialResult = wmNewsMaterialMapper.insert(newsMaterial);
            if (newsMaterialResult < 1) {
                throw new RuntimeException("wm_news_material表更新失败");
            }
        }
        return true;
    }

    //将newsDto转为news
    public WmNews newsDto2News(WmNewsDto dto){
        //0.入参判空
        if (dto == null) {
            return null;
        }

        //1.数据拷贝
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto,wmNews);

        //传入dto中没有的参数
        //1.1userId,ThreadLocal提取
        wmNews.setUserId(UserThreadLocal.get().getId());
        //1.2type,如果type=-1(没有指定封面)要单独处理,从内容图片中提取图片
        if (wmNews.getType() == -1) {
            return null;
        }
        //1.3creatTime
        wmNews.setCreatedTime(new Date());
        //1.4images以List<String>传入
        List<String> imagesList = dto.getImages();
        //列表处理前要判空
        if (!CollectionUtils.isEmpty(imagesList)) {
            String join = StringUtils.join(imagesList, ",");
            wmNews.setImages(join);
        }
        wmNews.setEnable((short) 1);
        return wmNews;
    }

    //得到内容中的图片
    public List<String> getContentImage(String content){

        //入参判空
        if (StringUtils.isEmpty(content)) {
            return new ArrayList<>();
        }


        List<String> stringList = new ArrayList<>();
        //面对集合时必须进行两次判空,一次集合判空,一次集合内容for循环时判空
        List<Map> mapList = JSON.parseArray(content,Map.class);
        if (!CollectionUtils.isEmpty(mapList)) {
            return new ArrayList<>();
        }

        for (Map map : mapList) {
            if (map == null) {
                continue;
            }
            //这里没有先进行type类型对比,这样查询会报错没有image这个键;键只有type和value
            //String image = (String) map.get("image");
            //先查询键为image的
            Object type = map.get("type");
            if ("image".equals(type)) {
                //将键相同的map的值取出
                String image = (String) map.get("value");
                stringList.add(image);
            }
        }
        return stringList;
    }

    //得到封面图
    public List<String> getCoverImage(Short type, List<String> coverImage, List<String> contentImage){
        if (type == -1) {
            int size = contentImage.size();

            if (size >= 3) {
                return contentImage.subList(0, 3);
            } else if (size == 2) {
                return contentImage.subList(0, 2);
            } else if (size == 1) {
                String s = contentImage.get(0);
                ArrayList<String> list = new ArrayList<>();
                list.add(s);
                return list;
            }else {
                //内容中一张图没有
                return new ArrayList<>();
            }
        }
        //如果type!=-1就使用封面中
        return coverImage;
    }

    //上架/下架
    @Override
    public ResponseResult upOrDown(WmNewsDto dto) {

        //0.两个入参判空
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //1.根据传入id查询新闻
        WmNews wmNews = wmNewsService.getById(dto.getId());
        if (wmNews == null) {
            log.warn("数据库中没有此新闻");
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //2.判断新闻是否已经发布
        if (wmNews.getStatus() != 9) {
            log.warn("文章未发布,无法下架");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //3.修改新闻的enable字段
        wmNews.setEnable(dto.getEnable());
        boolean updateResult = wmNewsService.updateById(wmNews);
        if (!updateResult) {
            log.warn("数据库修改失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }

        //4.向kafaka中发送消息
        Map<String,Object> map = new HashMap<>();
        map.put("article",wmNews.getArticleId());
        map.put("enable",dto.getEnable());
        kafkaTemplate.send("wmnews.up.or.down", JSON.toJSONString(map));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
